#ifndef CONNECTION_HPP_
#define CONNECTION_HPP_

#include <string>
#include <time.h>
#include "exception/Exception.hpp"

namespace SystemSocket
{
	/***
	 * Exceptions as only few, they are not in a seperate file
	 */
	class WriteException : public Exception::BaseException
	{
		public:
			WriteException():BaseException("Couldn't write on the connection"){}
	};

	class ReadException : public Exception::BaseException
	{
		public:
			ReadException():BaseException("Couldn't read on the connection"){}
	};
	/**
	 * This class abstracts the way we handle connections and tries to hide some of
	 * POSIX/Socket implementation details. It provides very basic interface to
	 * read/write over active socket descriptor and a way to check if the socket is active
	 * or not. As in case of the followermaze task, we can't send any messages over
	 * the socket to the client, than those defined in the task description,  we monitor socket
	 * activity. If there was no action related to the socket for some time defined in
	 * MAX_INACTIVITY_TIME constant, we may consider this socket as invalid, but this is left
	 * to the client to periodically check for socket validity.
	 */
	class Connection
	{
	public:
		/**
		 * Nothting special. Just construction of socket descriptor wrapper. Notice that creating
		 * the active socket is the first timestamp that will be considered in monitoring socket
		 * activity.
		 *
		 * \param iActiveSocketFd socket descriptor to be wrapped.
		 */
		Connection(int iActiveSocketFd):
			_activeSockedFd(iActiveSocketFd),
			_forceInvalid(false)
		{

		}
		/**
		 * Just a destructor. Should close the connection if it wasn't done yet.
		 */
		virtual ~Connection();
		/**
		 * Reads from the socket as long as the newline character is not met. It was implemented
		 * like dead to protect against a situation when there are already several messages
		 * waiting to be read. As we can read in the task description every message is ended by
		 * 0x0A character, so we process the input as long as we got this character. After this
		 * method is over the timestamp of socket activity is also updated. The method wraps
		 * POSIX/read call.
		 *
		 * \return The string that was read, or exceptions if the connections didn't work.
		 */
		virtual std::string read();
		/**
		 * Writes to the socket the given string using POSIX/write method. Throws an exceptions
		 * when we can't write to the socket anymore.
		 */
		virtual void write(std::string);
		/**
		 * Closes the connection.
		 */
		virtual void close();
		/**
		 * The method bases on the timestamp of last use of the socket. If given time elapsed
		 * from the last usage of the socket we may consider it as invalid, but it's up to
		 * the user to decide what to do then. Before we go for time checking, we check if
		 * the connection was closed before. Then is invalid.
		 *
		 * \return true if the connection is open and was used within last MAX_INACTIVITY seconds
		 */
		virtual bool isValid();

		/**
		 * This method allows to set exception as invalid. In example when we want to get rid off it
		 * or we got an exception.
		 */
		virtual void markInvalid() {_forceInvalid = true;}

	private:
		int _activeSockedFd;
		bool _forceInvalid;
	};
};

#endif /* CONNECTION_HPP_ */
